package org.finesys.common.security.client.service;

import org.finesys.common.security.authentication.gitee.GiteeTokenResponse;
import org.finesys.common.security.authentication.gitee.GiteeUserInfoResponse;
import org.finesys.common.security.client.properties.GiteeProperties;
import org.springframework.security.config.Customizer;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.oauth2.core.OAuth2AuthenticationException;
import org.springframework.security.oauth2.server.authorization.config.annotation.web.configurers.OAuth2AuthorizationServerConfigurer;
import org.springframework.security.oauth2.server.authorization.config.annotation.web.configurers.OAuth2TokenEndpointConfigurer;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;

public interface GiteeRegisteredClientRepository {

    /**
     * 根据appId获取重定向地址
     *
     * @param appId 码云Gitee client_id
     * @return 返会重定向地址
     */
    String getRedirectURIByAppId(String appId);

    /**
     * 生成状态码
     */
    String stateGenerate(String appId);

    /**
     * @param id     码云用户唯一标识
     * @param appId  开放平台 网站应用 ID
     * @param userId 系统用户id
     */
    void storeBinding(Long id, String appId, Long userId);

    /**
     * 根据 AppID(码云Gitee client_id)、code、jsCode2SessionUrl 获取Token
     *
     * @param appId          AppID(码云Gitee
     *                       client_id)，<a href="https://gitee.com/api/v5/oauth_doc">OAuth文档</a>
     * @param code           授权码，<a href="https://gitee.com/api/v5/oauth_doc">OAuth文档</a>
     * @param accessTokenUrl <a href="https://gitee.com/api/v5/oauth_doc">OAuth文档</a>
     * @return 返回 码云Gitee授权结果
     * @throws OAuth2AuthenticationException OAuth 2.1 可处理的异常，可使用
     *                                       {@link OAuth2AuthorizationServerConfigurer#tokenEndpoint(Customizer)} 中的
     *                                       {@link OAuth2TokenEndpointConfigurer#errorResponseHandler(AuthenticationFailureHandler)}
     *                                       拦截处理此异常
     */
    GiteeTokenResponse getAccessTokenResponse(String appId, String code, String accessTokenUrl);

    /**
     * 获取授权用户的资料
     *
     * @param userinfoUrl        用户信息接口
     * @param appId              AppID(码云Gitee client_id)
     * @param state              状态码
     * @param giteeTokenResponse 码云 Token
     * @return 返回授权用户的资料
     * @see <a href="https://gitee.com/api/v5/swagger#/getV5User">获取授权用户的资料</a>
     */
    GiteeUserInfoResponse getUserInfo(String userinfoUrl, String appId, String state, GiteeTokenResponse giteeTokenResponse);

    /**
     * 储存gitee用户
     *
     * @param giteeTokenResponse    gitee token信息
     * @param giteeUserInfoResponse gitee用户信息
     * @param appId                 码云网站应用ID
     */
    void storeGiteeUsers(GiteeTokenResponse giteeTokenResponse, GiteeUserInfoResponse giteeUserInfoResponse, String appId);

    /**
     * 标记此次操作用户
     *
     * @param appId
     * @param state
     * @param userId
     */
    void tagUsers(String appId, String state, Long userId);

    /**
     * 获取此次操作用户
     *
     * @param appId
     * @param state
     * @return
     */
    String getTagUser(String appId, String state);

    /**
     * 获取登录系统的用户信息
     *
     * @param appId 码云应用id
     * @param id    码云用户唯一标识
     * @return 系统用户信息
     */
    UserDetails getUser(String appId, Long id);

    /**
     * 根据 appid 获取 码云Gitee属性配置
     *
     * @param appId 码云Gitee client_id
     * @return 返回 码云Gitee属性配置
     * @throws OAuth2AuthenticationException OAuth 2.1 可处理的异常，可使用
     *                                       {@link OAuth2AuthorizationServerConfigurer#tokenEndpoint(Customizer)} 中的
     *                                       {@link OAuth2TokenEndpointConfigurer#errorResponseHandler(AuthenticationFailureHandler)}
     *                                       拦截处理此异常
     */

    GiteeProperties.Gitee getGiteeByAppId(String appId);

    /**
     * 状态码验证（返回 {@link Boolean#FALSE} 时，将终止后面需要执行的代码）
     *
     * @param appId 开放平台 网站应用 ID
     * @param code  授权码
     * @param state 状态码
     * @return 返回 状态码验证结果
     */
    boolean stateValid(String appId, String code, String state);
}
